package com.blrs.service.file.impl;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.blrs.common.core.domain.entity.SysUser;
import com.blrs.common.exception.ServiceException;
import com.blrs.common.utils.SecurityUtils;
import com.blrs.common.utils.StringUtils;
import com.blrs.domain.*;
import com.blrs.mapper.ExternalDocumentMapper;
import com.blrs.mapper.FileCabinetInformationMapper;
import com.blrs.mapper.FileChangeRecordMapper;
import com.blrs.system.mapper.SysDictDataMapper;
import com.blrs.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.blrs.mapper.InternalDocumentMapper;
import com.blrs.service.file.IInternalDocumentService;

/**
 * 内部文件Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-11-01
 */
@Service
public class InternalDocumentServiceImpl implements IInternalDocumentService 
{

    @Autowired
    private InternalDocumentMapper internalDocumentMapper;
    @Autowired
    private FileCabinetInformationMapper fileCabinetInformationMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDictDataMapper sysDictDataMapper;
    @Autowired
    private FileChangeRecordMapper fileChangeRecordMapper;
    @Autowired
    private ExternalDocumentMapper externalDocumentMapper;


    @Override
    public List<Map> getFileTree(FileCabinetInformation fileCabinetInformation) {
        List<FileCabinetInformation> types=internalDocumentMapper.selectFileCabinetInformationListFileTree(fileCabinetInformation);
        List<FileCabinetInformation> fList=types.stream().filter(obj->obj.getSuperiorCabinetId().equals("00000000-0000-0000-0000-000000000000")).collect(Collectors.toList());
        List<FileCabinetInformation> zList=types.stream().filter(obj->!obj.getSuperiorCabinetId().equals("00000000-0000-0000-0000-000000000000")).collect(Collectors.toList());
        List<Map> list=new ArrayList<>();
        for (FileCabinetInformation info : fList) {
            Map map=new HashMap<>();
            map.put("id",info.getCabinetId());
            map.put("idPath",info.getIdPath());
            map.put("parentId",info.getSuperiorCabinetId());//上级
            map.put("label",info.getCabinetName());
            List<Map> listMap=list(zList,info.getCabinetId());
            if(listMap.size()!=0){
                map.put("children",listMap);
            }
            list.add(map);
        }
        return list;
    }
    @Override
    public List<FileCabinetInformation> selectFileCabinetInformationListFileTree(FileCabinetInformation fileCabinetInformation)
    {
        return internalDocumentMapper.selectFileCabinetInformationListFileTree(fileCabinetInformation);
    }
    private List<Map> list(List<FileCabinetInformation> zList, String parentId){
        List<Map> list=new ArrayList<>();
        for (FileCabinetInformation info : zList) {
            if(info.getSuperiorCabinetId().equals(parentId)){
                Map map=new HashMap<>();
                map.put("id",info.getCabinetId());
                map.put("idPath",info.getIdPath());

                map.put("label",info.getCabinetName());
                List<Map> listMap=list(zList,info.getCabinetId());
                if(listMap.size()!=0){
                    map.put("children",listMap);
                }
                list.add(map);
            }
        }
        return list;
    }
    /**
     * 查询内部文件
     * 
     * @param internalId 内部文件主键
     * @return 内部文件
     */
    @Override
    public InternalDocument selectInternalDocumentByInternalId(String internalId)
    {
        return internalDocumentMapper.selectInternalDocumentByInternalId(internalId);
    }

    /**
     * 查询内部文件列表
     * 
     * @param internalDocument 内部文件
     * @return 内部文件
     */
    @Override
    public List<InternalDocument> selectInternalDocumentList(InternalDocument internalDocument)
    {
        //公司管理员可看到所有文件
        String id = SecurityUtils.getLoginUser().getUser().getIsAdmin();
        if(SecurityUtils.getLoginUser().getUser().getIsAdmin().equals("1")){
            internalDocument.setBelongTo(SecurityUtils.getOrgId());
            return internalDocumentMapper.selectInternalDocumentListAdmin(internalDocument);
        }else{
            internalDocument.setPermissionUserId(SecurityUtils.getUserId());
            internalDocument.setEstablishedId(SecurityUtils.getUserId());
            List<InternalDocument> internalDocuments = internalDocumentMapper.selectInternalDocumentList(internalDocument);
            // 使用Stream API去除internalId相同的数据
            List<InternalDocument> optimizedDocuments = internalDocuments.stream()
                    .filter(Objects::nonNull) // 过滤掉null值，避免空指针异常
                    .collect(Collectors.collectingAndThen(
                            Collectors.toMap(
                                    InternalDocument::getInternalId, // 键为internalId
                                    doc -> doc, // 值为internalDocument对象本身
                                    (existing, replacement) -> existing // 如果有重复的internalId，保留第一个
                            ),
                            map -> new ArrayList<>(map.values()) // 将map中的值转换为list
                    ));
            return optimizedDocuments;
        }
    }

    @Override
    public List<InternalDocument> selectInternalDocumentListByAdmin(InternalDocument internalDocument)
    {

        return internalDocumentMapper.selectInternalDocumentListByAdmin(internalDocument);
    }
    /**
     * 新增内部文件
     * 
     * @param internalDocument 内部文件
     * @return 结果
     */
    @Override
    public int insertInternalDocument(InternalDocument internalDocument)
    {
        //internalDocument.setInternalId(UUID.randomUUID().toString());
//        FileCabinetInformation data = selectFileCabinetInformationByCabinetId(internalDocument.getCabinetId());
//        internalDocument.setCabinetName(data.getCabinetName());//上级文件柜
        //判重，如果相同文件夹下有同名文件，则报错
        List<InternalDocument> document=internalDocumentMapper.selectInternalDocumentByFileNameAndCabinetId(internalDocument.getFileName(),internalDocument.getCabinetId(),SecurityUtils.getOrgId());
        if (StringUtils.isNotEmpty(document)){
             throw new  ServiceException("文件夹下有同名文件，不能重复上传!!");
        }
        internalDocument.setCreationId(SecurityUtils.getUserId());
        internalDocument.setEstablishedId(SecurityUtils.getUserId());
        internalDocument.setCreationName(SecurityUtils.getUsername());
        internalDocument.setCreationTime(new Timestamp(new Date().getTime()));
        internalDocument.setOrganizationId(SecurityUtils.getOrgId());
        internalDocument.setOrganizationName(SecurityUtils.getOrgName());
        internalDocument.setDepartmentId(SecurityUtils.getDeptId());
        internalDocument.setBelongTo(SecurityUtils.getOrgId());
        if (StringUtils.isEmpty(internalDocument.getInternalId()) || "".equals(internalDocument.getInternalId())){
            internalDocument.setInternalId(UUID.randomUUID().toString().replaceAll("-",""));
        }
        return internalDocumentMapper.insertInternalDocument(internalDocument);
    }
    public FileCabinetInformation selectFileCabinetInformationByCabinetId(String cabinetId)
    {
        return fileCabinetInformationMapper.selectFileCabinetInformationByCabinetId(cabinetId);
    }
    /**
     * 修改内部文件
     * 
     * @param internalDocument 内部文件
     * @return 结果
     */
    @Override
    public int updateInternalDocument(InternalDocument internalDocument)  throws NoSuchFieldException, IllegalAccessException{
        //先用操作人姓名来暂存修改类型 1=修改 变更 2=权限设置
        if(internalDocument.getOperateName().equals("1")){
            //先获取原始数据
            InternalDocument data = internalDocumentMapper.selectInternalDocumentByInternalId(internalDocument.getInternalId());
            //利用反射获取两个对象的差异属性有哪些
            Map<String, String> stringObjectMap = comparePurchasing(data, internalDocument);
            if (stringObjectMap.size()>0) {
                StringBuilder sb = new StringBuilder();
                for (Map.Entry<String, String> entry : stringObjectMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key).append(":").append(value).append(",");
                }
                // 删除最后一个逗号
                if (sb.length() > 0) {
                    sb.deleteCharAt(sb.length() - 1);
                }
                //变更内容
                FileChangeRecord record = new FileChangeRecord();
                record.setInternalId(internalDocument.getInternalId());
                record.setChangeContent(sb.toString());//变更内容
                record.setChangeTime(new Timestamp(new Date().getTime()));
                record.setChangedId(SecurityUtils.getUserId().toString());
                record.setChangedName(SecurityUtils.getUsername());
                record.setRecordId(UUID.randomUUID().toString().replaceAll("-",""));
                fileChangeRecordMapper.insertFileChangeRecord(record);
            }
        }else if(internalDocument.getOperateId().equals("2")){
            //权限设置保存后 复制数据存入外部文件
            ExternalDocument externalDocument = new ExternalDocument();
            externalDocument.setExternalId(internalDocument.getInternalId());
            // 新插入的数据默认存放再外部文件柜下
            externalDocument.setCreationId(internalDocument.getCreationId());
            externalDocument.setFileName(internalDocument.getFileName());
            externalDocument.setCabinetId("650c44e1-b575-4b62-9d54-1ba9d1e8abb7");//外部文件
            externalDocument.setDocumentNumber(internalDocument.getDocumentNumber());
            externalDocument.setEstablishmentTime(internalDocument.getEstablishmentTime());
            externalDocument.setEstablishedId(internalDocument.getEstablishedId().toString());
            externalDocument.setEstablishedName(internalDocument.getEstablishedName());
            externalDocument.setEffectiveTime(internalDocument.getEffectiveTime());
            externalDocument.setVersion(internalDocument.getVersion());
            externalDocument.setManagementDepartment(internalDocument.getManagementDepartment());
            externalDocument.setReadWritePermission(internalDocument.getReadWritePermission());
            externalDocument.setReadWritePermissionId(internalDocument.getReadWritePermissionId());
            externalDocument.setState("0");
            externalDocument.setCreationId(internalDocument.getCreationId());
            externalDocument.setCreationName(internalDocument.getCreationName());
            externalDocument.setCreationTime(internalDocument.getCreationTime());
            externalDocument.setOrganizationId(internalDocument.getOrganizationId());
            externalDocument.setOrganizationName(internalDocument.getOrganizationName());
            externalDocument.setDepartmentId(internalDocument.getDepartmentId());
            externalDocument.setBelongTo(internalDocument.getBelongTo());
            return externalDocumentMapper.insertExternalDocument(externalDocument);
        }
//        FileCabinetInformation data = selectFileCabinetInformationByCabinetId(internalDocument.getCabinetId());
//        internalDocument.setCabinetName(data.getCabinetName());//上级文件柜
        internalDocument.setOperateTime(new Timestamp(new Date().getTime()));
        internalDocument.setOperateName(SecurityUtils.getUsername());
        internalDocument.setOperateId(SecurityUtils.getUserId());
        return internalDocumentMapper.updateInternalDocument(internalDocument);
    }
    public  Map<String,String> comparePurchasing(InternalDocument purchasing, InternalDocument purchasing1) throws NoSuchFieldException, IllegalAccessException {
        HashMap<String, String> map = new HashMap<>();
        HashMap<String, Object> changeMap = new HashMap<>();
        Field fileName = InternalDocument.class.getDeclaredField("fileName");
        Field cabinetName = InternalDocument.class.getDeclaredField("cabinetName");
        Field documentNumber = InternalDocument.class.getDeclaredField("documentNumber");
        //Field effectiveTime = InternalDocument.class.getDeclaredField("effectiveTime");
        Field state = InternalDocument.class.getDeclaredField("state");
        Field version = InternalDocument.class.getDeclaredField("version");
        //Field state = InternalDocument.class.getDeclaredField("state");
        changeMap.put("文件名称",fileName);
        changeMap.put("文件柜名称",cabinetName);
        changeMap.put("文件编号",documentNumber);
        //changeMap.put("生效时间",effectiveTime);
        changeMap.put("版本",version);
        changeMap.put("状态",state);
        //changeMap.put("附件",fileUpload);
        for (Map.Entry<String, Object> entry : changeMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            Field field = (Field) value;
            field.setAccessible(true); // 设置访问权限为可访问
            Object value1 = field.get(purchasing);
            Object value2 = field.get(purchasing1);
           if (key.equals("状态")){
                if (!value1.equals(value2)){
                    String dictName1=sysDictDataMapper.selectDictDataByValueAndType((String)value1,"file_status");
                    String dictName2=sysDictDataMapper.selectDictDataByValueAndType((String)value2,"file_status");
                    map.put(key,dictName1+"变更为"+dictName2);
                }
           }else {
                // 比较属性值是否相等
                if ((value1 != null && value2 != null && !value1.equals(value2)) ) {
                    if (value1 instanceof BigDecimal){
                        BigDecimal val1=(BigDecimal) value1;
                        BigDecimal val2=(BigDecimal) value2;
                        if (val1.compareTo(val2)!=0){
                            map.put(key, value1+"变更为"+value2);
                        }
                    } else {
                        map.put(key, value1+"变更为"+value2);
                    }

                }
            }
           /*else if (key.equals("生效时间")){
                if (!value1.equals(value2)){
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    String format = simpleDateFormat.format((Date) value1);
                    String format1 = simpleDateFormat.format((Date) value2);
                    map.put(key,format+"变更为"+format1);
                }*/
        }

        return map;
    }
    /**
     * 批量删除内部文件
     * 
     * @param internalIds 需要删除的内部文件主键
     * @return 结果
     */
    @Override
    public int deleteInternalDocumentByInternalIds(String[] internalIds)
    {
        return internalDocumentMapper.deleteInternalDocumentByInternalIds(internalIds);
    }

    /**
     * 删除内部文件信息
     * 
     * @param internalId 内部文件主键
     * @return 结果
     */
    @Override
    public int deleteInternalDocumentByInternalId(String internalId)
    {
        return internalDocumentMapper.deleteInternalDocumentByInternalId(internalId);
    }
}
